I have found some ways around the issue, but none of them are ideal. I’m sure there are better ways than the ones I’ve listed, but I was unable to find them.

Map individually
Rather than trying to get all People in a single query, query per extended class and join the results as shown below:

        List<Person> people = template.find(new Query(Criteria.where("_class").is("person")),Person.class,collection);
        List<Employee> employees = template.find(new Query(Criteria.where("_class").is("employee")),Employee.class,collection);
        people.addAll(employees);

The issue with this is that I would have to remember to add each new class that extends from Person to any query for that collection.

Remove Inheritance
This would involve moving every property from the inheritors of Person. This means I can still keep number of queries down, but will make the Person class large and require lots of branching logic based on which type of Person it is.

Manually Mapping
Rather than mapping the mongo response to a Person, map it to a BSON Document class that is then converted into the correct Person as shown below:

PersonMapper.java

package com.example.demo;

import org.bson.Document;

import java.util.List;
import java.util.stream.Collectors;

public class PersonMapper {

    public static Person MapPerson(Document document){
        String typeAlias = document.getString("_class");
        String name =  document.getString("name");
        String id = document.getString("_id");

        switch (typeAlias){
            default:
                return new Person(id,name);
            case "employee":
                String jobTitle = document.getString("jobTitle");
                return new Employee(id,name,jobTitle);
            case "student":
                String major = document.getString("major");
                return new Student(id,name,major);
        }
    }
    public static List<Person> MapPeople(List<Document> documentList){
        return documentList.stream().map(document -> MapPerson(document)).collect(Collectors.toList());
  }
}

This adds the issue of manually adding new types to the mapper as well as ensuring the mapper reflects any changes to existing People classes.