The idea is to push the elements only once if they do not exist in the resultant words list. You can use a loop, std::count, std::find, etc. to verify the non-existence of the elements. Or, you can also use std::unique directly.
With a loop, it would be something like this (live):
using Words = std::vector<std::string>;
Words findUniqueWords( const Words& words )
{
    Words uniqueWords;
    uniqueWords.push_back( words[0] );
    for ( int i = 1; i < words.size(); ++i )
    {
        bool isAdded = false;
        for ( int j = 0; j < uniqueWords.size(); ++j )
        {
            if ( words[i] == uniqueWords[j] )
            {
                isAdded = true;
                break;
            }
        }
        if ( !isAdded )
        {
            uniqueWords.push_back( words[i] );
        }
    }
    return uniqueWords;
}
Here's an example with std::count (live):
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using Words = std::vector<std::string>;
Words findUniqueWords( const Words& words )
{
    Words uniqueWords;
    uniqueWords.push_back( words[0] );
    for ( int i = 1; i < words.size(); ++i )
    {
        if ( std::count( uniqueWords.cbegin(), uniqueWords.cend(), words[i] ) == 0 )
        {
            uniqueWords.push_back( words[i] );
        }
    }
    return uniqueWords;
}
int main()
{
    const Words words { "abc", "xyz", "abc", "xyz", "jkl" };
    const auto result = findUniqueWords( words );
    for ( const auto& word : result )
    {
        std::cout << word << '\n';
    }
    return 0;
}
Output:
abc
xyz
jkl
Also, you need to take care of the case when the input words is an empty list.
Relevant thread: Why is "using namespace std;" considered bad practice?