You don't need RTTI to deserialize data in a clean way. What you need is return-type polymorphism. Haskell has this and it makes writing serializers and deserializers symmetric and totally painless.
Return type polymorphism and inheritance doesn't mix very well.
Swift got into this mess early in it's lifecycle and it's type checking is still more expensive than the rest of the compiler combined, and unpredictable on top of that.
C++ has both return type polymorphism and inheritance. What it doesn't have is the kind of type inference that Haskell has. Its type inference is very limited.
That is still polymorphic, but as I mentioned C++ does not do the kind of type deduction that Haskell supports so you do have to explicitly instantiate the template. However, you can instantiate it based on context, for example using decltype.
You certainly can and I know there are several JSON libraries that do it. The gist of it is to write a struct and overload the conversion operator for the set of return types you want to support, for example overload the conversion operator to int and std::string. As soon as the instance of that struct is used in a context that needs an std::string, then it calls the string overload.