A C++20 draft which seems to be working:
template<typename U, typename... Ts>
constexpr auto get(std::tuple<Ts*...> const& tuple) {
    std::array constexpr candidates{std::derived_from<U, Ts>...};
    static_assert(std::ranges::count(candidates, true) == 1);
    return get<std::ranges::equal_range(candidates, false).size()>(tuple);
}
For some evil reason, this question is tagged as c++11 (which I'm not good at) so I tried to backport my idea. Maybe the following version is suboptimal but I hope that it at least works and this much of constexprless horror is enough.
/*
Parameters:
    the index of the current tuple type being examined
    whether it fits
    the derived type
    the next remaining tuple type
    other remaining tuple types
*/
template<std::size_t, bool, typename...> struct Helper
{ static auto constexpr value = SIZE_MAX; };
template<std::size_t i, typename U, typename T, typename... Ts>
struct Helper<i, false, U, T, Ts...>
: Helper<i + 1, std::is_base_of<T, U>::value, U, Ts...>
{};
template<std::size_t i, typename U, typename... Ts>
struct Helper<i, true, U, Ts...>
{ static auto constexpr value = i; };
template<std::size_t i, typename U, typename T, typename... Ts>
struct Helper<i, true, U, T, Ts...> {
    static auto constexpr value = i;
    static_assert(
        Helper<i + 1, std::is_base_of<T, U>::value, U, Ts...>::value == SIZE_MAX,
        "ambiguous"
    );
};
template<typename U, typename T, typename... Ts>
auto get(std::tuple<T*, Ts*...> const& tuple)
-> typename std::remove_reference<decltype(std::get<
    Helper<0, std::is_base_of<T, U>::value, U, Ts...>::value
>(tuple))>::type {
    return std::get<
        Helper<0, std::is_base_of<T, U>::value, U, Ts...>::value
    >(tuple);
}