Alternatively, you could write wrapper classes Int and String that inherit from an Object class. That would be a lot safer. Or you could use Boost.Any.
The first point to note is that there is no resource leak; even after conversion to std::shared_ptr<void>, the resources would be released correctly. (std::shared_ptr<void> stores a copy of the type-erased deleter of the original shared pointer that was created with std::make_shared<>, and applies that deleter when the last reference to the object is released).
The second point is that there are better design alternatives to exploit the strong type system that C++ has: switching on a type field and casting appropriately depending on that engenders hard-to-maintain, error-prone code. Using std::variant<> (C++17) or boost::variant<> would be a good design choice here.