Historically, Any was not marked as a class in typeshed, but pyright, mypy and other type checkers implemented special casing to enable it to be used as a class base anyway. TypedDict is similarly not a class in typeshed, but pyright, mypy and other type checkers allow classes to inherit from it. I think type checkers should implement similar special casing for NamedTuple.
Having NamedTuple as a class makes little sense. It is a function at runtime, and having it as a class in the stubs leads type checkers to make many incorrect inferences. For example, pyright believes that NamedTuple has a __mro__ attribute (it does not at runtime), and believes that NamedTuple does not have a __kwdefaults__ attribute (it does at runtime). It also believes that NamedTuple is a valid type expression, even though it is impossible to construct any object at runtime that is an “instance of NamedTuple” (since NamedTuple is a function), and it believes that type[NamedTuple] is a valid type expression, even though it is impossible to construct a class at runtime that has NamedTuple in its MRO (because NamedTuple is a function – classes that “inherit from NamedTuple” are in fact direct subclasses of tuple at runtime).
I strongly agree that we should keep TypedDictFallback and NamedTupleFallback in the _typeshed namespace indefinitely. I stated this in Remove type checker-specific symbols from builtins.pyi and typing.pyi · Issue #7580 · python/typeshed · GitHub as well, and @rchen152 agrees too.