Ms Sql Server Table Design question Background

I'm designing a table which will serve as a repository of payment information to be used for research purposes. This table will have around 4.5 million records initially and will grow at a rate of around 400k annually. The PaymentReference column would be the only unique column in the table on an on going basis meaning after the initial historical load of data which would contain nulls.   

Table example:

    CREATE TABLE [dbo].[Bil_ReturnsRepository](
    [ID] [bigint] IDENTITY(1,1) NOT NULL,
    [PolicyNumber] [nvarchar](32) NOT NULL,
    [PaymentReference] [nvarchar](32) NULL,
    [AccountingDate] [datetime] NOT NULL,
    [ReturnDate] [datetime] NOT NULL,
    [PaymentAmount] [decimal](19, 2) NOT NULL,
    [RegionCode] [nvarchar](5) NULL,
    [PolicyStateCode] [nvarchar] (3) NULL,
    [CompanyCode] [nvarchar](4) NULL,
    [LineOfBusiness] [nvarchar](4) NULL,
    [ReturnReasonCode] [nvarchar](3) NULL,
    [PaymentType] [nvarchar](20) NULL,
    [PaymentPlan] [nvarchar](20) NULL,
    [EntryUserId] [nvarchar](20) NULL,
    [PolicyTermId] [bigint] NULL,
    [PaymentDate] [datetime] NULL,
    [DateOfFirstReturn] [datetime] NULL,
    [BankId] [nvarchar](9) NULL,
    [EquityDateOfPolicy] [datetime] NULL,
    [OrginalStartDateOfPolicy] [datetime] NULL,
    [PaymentSource] [nvarchar](20) NULL,
    [DBTransactionTimeStamp] DATETIME NOT NULL DEFAULT(GETDATE()))


Access to Data

Business users will enter search criteria on a front end UI screen. The available options to use as search criteria will be every column located on the table except ID and DBTransactionTimeStamp. Every column of the table will have an associated text box that the user will have the ability to enter the necessary value for that column to use for the search. The only field that is not optional for the search is the ReturnDate field. For example, a search could be performed with just ReturnDate and PolicyNumber. ReturnDate, PaymentReference. ReturnDate, PolicyNumber, PaymentReference, AccountingDate. ReturnDate only. etc.... 

A stored procedure will be created to actually perform the read of the table and will use the parameters passed by the front end UI when querying the table. 

Question 

Since this is a new design I'm not currently experiencing any performance issues but I would like to be proactive and prevent any of those possible issues from occurring. I would imagine that with so many records on the table and the ability to search on all fields there would be table space scans that would occur. That would result in a slow response time for the output to be returned to the front end UI.  So with that being said would it be beneficial to add any indexes and or keys to this table ? If so what Keys ? What indexes ?
Since the search always includes the ReturnDate column, it seems reasonable to create the clustered index on that column.
Based on your stated assumption that you'll add around 400,000 rows per year, and you have 4,000,000 rows in the table now, it seems like you might reasonably have 10 years of data, or 3650 unique ReturnDate values at the current time.  (4,000,000 / 400,000 = 10)
With the clustered index on ReturnDate, selectivity on the clustered index would be on average around 1,300 rows per ReturnDate value.
If SQL Server does a seek into the clustered index to the start of the range of values fitting the desired ReturnDate, it will only need to scan approximately 1,300 rows to find the other values to fit the search criteria.
I've setup a simple test-bed to test this hypothesis:
IF OBJECT_ID(N'dbo.Bil_full', N'U') IS NOT NULL DROP TABLE dbo.Bil_full;

CREATE TABLE dbo.Bil_full
(
      PolicyNumber nvarchar(32) NOT NULL
    , PaymentReference nvarchar(32) NULL
    , AccountingDate datetime NOT NULL
    , ReturnDate datetime NOT NULL
    , PaymentAmount decimal(19, 2) NOT NULL
    , RegionCode nvarchar(5) NULL
    , PolicyStateCode nvarchar (3) NULL
    , CompanyCode nvarchar(4) NULL
    , LineOfBusiness nvarchar(4) NULL
    , ReturnReasonCode nvarchar(3) NULL
    , PaymentType nvarchar(20) NULL
    , PaymentPlan nvarchar(20) NULL
    , EntryUserId nvarchar(20) NULL
    , PolicyTermId bigint NULL
    , PaymentDate datetime NULL
    , DateOfFirstReturn datetime NULL
    , BankId nvarchar(9) NULL
    , EquityDateOfPolicy datetime NULL
    , OrginalStartDateOfPolicy datetime NULL
    , PaymentSource nvarchar(20) NULL
    , DBTransactionTimeStamp DATETIME NOT NULL 
        CONSTRAINT DF_bil_ts
        DEFAULT(GETDATE())
) ON [PRIMARY];

CREATE CLUSTERED INDEX CX_Bil
ON dbo.Bil_full(ReturnDate);

Here, I'm adding 4,000,000 rows to the table, with a variety of &quot;made-up&quot; data that perhaps approximates the data you might actually have.
;WITH src AS (
    SELECT num = 1.0 + v1.num 
        + (v2.num * 10) 
        + (v3.num * 100)
        + (v4.num * 1000)
        + (v5.num * 10000) 
        + (v6.num * 100000) 
        + (v7.num * 1000000) 
    FROM  (VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9))v1(num)
        , (VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9))v2(num)
        , (VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9))v3(num)
        , (VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9))v4(num)
        , (VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9))v5(num)
        , (VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9))v6(num)
        , (VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9))v7(num)
)
INSERT TOP(4000000) INTO dbo.Bil_full (PolicyNumber, PaymentReference, AccountingDate, ReturnDate, PaymentAmount, RegionCode, PolicyStateCode, CompanyCode, LineOfBusiness, ReturnReasonCode, PaymentType, PaymentPlan, EntryUserId, PolicyTermId, PaymentDate, DateOfFirstReturn, BankId, EquityDateOfPolicy, OrginalStartDateOfPolicy, PaymentSource, DBTransactionTimeStamp)
SELECT PolicyNumber = N'PN' + RIGHT(N'000000000' + CONVERT(nvarchar(10), src.num), 10)
    , PaymentReference = N'PR' + RIGHT(N'000000000' + CONVERT(nvarchar(10), src.num - 10000), 10)
    , AccountingDate = DATEADD(DAY, src.num % 3715, N'2012-01-01T00:00:00')
    , ReturnDate = DATEADD(DAY, src.num % 3715, N'2012-03-01T00:00:00')
    , PaymentAmount = src.num * CONVERT(int, CRYPT_GEN_RANDOM(1)) * 0.47
    , RegionCode = CASE WHEN src.num % 3 = 1 THEN REPLICATE(char(65 + src.num % 26), 5) ELSE NULL END
    , PolicyStateCode = CASE WHEN src.num % 3 = 2 THEN REPLICATE(CHAR(65 + src.num % 26), 3) ELSE NULL END
    , CompanyCode = CASE WHEN src.num % 5 = 3 THEN REPLICATE(CHAR(65 + src.num % 26), 4) ELSE NULL END
    , LineOfBusiness = CASE WHEN src.num % 6 = 3 THEN REPLICATE(CHAR(66 + src.num % 26), 4) ELSE NULL END
    , ReturnReasonCode = CASE WHEN src.num % 3 = 2 THEN REPLICATE(CHAR(69 + src.num % 26), 3) ELSE NULL END
    , PaymentType = CONVERT(varchar(10), CRYPT_GEN_RANDOM(8), 1)
    , PaymentPlan = CONVERT(varchar(10), CRYPT_GEN_RANDOM(8), 1)
    , EntryUserId = CONVERT(varchar(10), CRYPT_GEN_RANDOM(8), 1)
    , PolicyTermId = CONVERT(bigint, CRYPT_GEN_RANDOM(1))
    , PaymentDate = DATEADD(DAY, src.num % 3715, N'2012-01-01T00:00:00') + 27
    , DateOfFirstReturn = DATEADD(DAY, src.num % 3715, N'2012-03-01T00:00:00') - 16
    , BankId = CONVERT(varchar(8), CRYPT_GEN_RANDOM(6), 1)
    , EquityDateOfPolicy = DATEADD(DAY, src.num % 3715, N'2012-01-01T00:00:00') + 365
    , OrginalStartDateOfPolicy = DATEADD(DAY, src.num % 3715, N'2012-01-01T00:00:00') + 15
    , PaymentSource = CONVERT(varchar(10), CRYPT_GEN_RANDOM(8), 1)
    , DBTransactionTimeStamp = DATEADD(SECOND, src.num, N'2013-01-01T00:00:00')
FROM src
ORDER BY src.num

The table has 1346 rows per ReturnDate from 2012-03-05 to 2022-05-02.
Assuming every query against this table does in fact include a ReportDate value, you could expect execution to consist of a single clustered index seek, which is going to be quite efficient.
For instance, the query:
SELECT *
FROM dbo.Bil_full
WHERE Bil_full.ReturnDate = N'2016-04-01 00:00:00.000'
    AND Bil_full.PolicyNumber LIKE N'%89%'
    AND Bil_full.PaymentType LIKE N'XX%'

Has this query plan:

Statistics I/O shows the following:
Table 'Bil_full'. Scan count 1, logical reads 50, physical reads 0, 
  read-ahead reads 0, lob logical reads 0, lob physical reads 0, 
  lob read-ahead reads 0.

You may notice I've removed the ID column from the table.  If you don't need the column, why include it?  If the date columns do not include times, you can save some space per row by changing the data type to DATE instead of DATETIME.  The nvarchar(..) columns could be changed to just varchar(..) columns if you are not actually storing unicode data; if that is applicable those columns will become half the size they currently are.
I've not created a primary key on the table since your question makes no mention of requiring one for referential integrity or other requirements such as uniqueness.  The table does have a clustered index, which optimizes the physical layout of the table on disk versus the table being a simple heap.  The clustered index (i.e. the table itself) will experience a fair amount of page splits if the ReportDate value for rows being inserted are not monotonically increasing.
You asked about performing a range-scan for the ReportDate where your client is asking for rows between two dates - as in:
SELECT *
FROM dbo.Bil_full
WHERE Bil_full.ReturnDate &gt;= N'2016-04-01 00:00:00.000'
    AND Bil_full.ReturnDate &lt; N'2017-04-02 00:00:00.000'
    AND Bil_full.PolicyNumber LIKE N'%89%'

Queries like this will still perform relatively well; the above query returned 19432 rows very quickly.  Of course, the size of the date range will affect query performance. Keeping the ranges as small as possible, i.e. allowing a maximum range of 30 days, will ensure performance remains manageable.