Pointers (both raw and smart) express certain ownership. Thus, to pick a proper pointer, you need to decide on the ownership. If something owns an object, then if this something dies, the object has to die too. Does my best friend has to die if I die? I don't think so. Thus, I don't own my best friend. This rules out unique_ptr and shared_ptr, since those are owning smart pointers.
So we have two choices: weak_ptr or a raw pointer. This depends on how you are going to keep track of alive persons.
The simplest approach might be to rely on smart pointers to keep track of alive persons. This means, you have some storage of shared_ptr to all persons, and then you store weak_ptr to point to them from another persons. In this case I know that if I have a friend and weak_ptr::lock() returns nullptr, this means my friend is dead. Convenient, but not very flexible. E.g. imagine you need to issue a letter to a family when a person dies. When would you do this? In person's destructor? This would be mix of responsibilities. In a custom deleter of a shared_ptr<Person>? That would break encapsulation, since this custom deleter might have many functions.
Another approach is to keep track of alive persons by a dedicated manager. Again, you need some storage where all persons live. You can store them by value, or via shared_ptr - up to you. Then you store raw pointers to those objects. (Note: if you store them in a vector, which size is an object to change, storing raw pointer to them is not a good idea, because of possible reallocation). In this case you cannot tell by looking on a raw pointer, whether my best friend is still alive or not. We would need to check the manager to get this information. This is more flexible, but I'd say less safe, since we have dangling pointers built-in in our system.
I'd recommend not to store raw pointers for that's sake, but to go for an ID. Store person's ID instead, and have a registry of persons by ID. This registry will handle all the mess and will properly detect situation, when somebody wants to access a dead person, trigger a post-man to issue a letter to relatives, etc. This also allows to distinguish situations when I don't have a best friend and when my best friend is dead. weak_ptr would return nullptr in both of these situations.
PS If we were storing shared_ptr to best friends, that would mean a person would be alive only as long as they are someone's best friend... So true, but not in software development world, sorry.